package utils;

import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNLogEntry;
import org.tmatesoft.svn.core.SVNLogEntryPath;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager;
import org.tmatesoft.svn.core.internal.io.dav.DAVRepositoryFactory;
import org.tmatesoft.svn.core.internal.io.fs.FSRepositoryFactory;
import org.tmatesoft.svn.core.internal.io.svn.SVNRepositoryFactoryImpl;
import org.tmatesoft.svn.core.internal.wc.DefaultSVNOptions;
import org.tmatesoft.svn.core.io.SVNRepository;
import org.tmatesoft.svn.core.io.SVNRepositoryFactory;
import org.tmatesoft.svn.core.wc.*;

import java.io.File;
import java.util.*;

/**
 * Created by lincl on 2017/5/16.
 */
public class SVNUtils {
    public static SVNRepository repository = null;
    public static Set<String> pathSet = new HashSet<>();



    /**
     * 通过不同的协议初始化版本库
     */
    public static void setupLibrary() {
        DAVRepositoryFactory.setup();
        SVNRepositoryFactoryImpl.setup();
        FSRepositoryFactory.setup();
    }

    /**
     * 验证登录svn
     */
    public static SVNClientManager authSvn(String svnRoot, String username, String password) {
        // 初始化版本库
        setupLibrary();

        // 创建库连接
        try {
            repository = SVNRepositoryFactory.create(SVNURL
                    .parseURIEncoded(svnRoot));
        } catch (SVNException e) {
            e.printStackTrace();
            return null;
        }

        // 身份验证
        ISVNAuthenticationManager authManager = SVNWCUtil.createDefaultAuthenticationManager(username, password);
        // 创建身份验证管理器
        repository.setAuthenticationManager(authManager);

        DefaultSVNOptions options = SVNWCUtil.createDefaultOptions(true);
        SVNClientManager clientManager = SVNClientManager.newInstance(options,
                authManager);
        return clientManager;
    }


    //拷贝svn版本改动的文件
    public static void copyChangeList(Long[] versions, IFileModification fileModification) throws Exception {
        pathSet.clear();
        SVNClientManager sm = authSvn(FileUtils.SVN_PATH, FileUtils.USERNAME, FileUtils.PASSWORD);
        String[] root = new String[]{""};
        List<SVNLogEntry> entries;
        for(Long v : versions){
            entries = getSVNLog(v, v, root);
            copyChangeList(entries, FileUtils.LOCAL_PATH, FileUtils.OUT_PATH, fileModification);
        }
        sm.dispose();
    }

    //拷贝svn版本改动的文件
    public static void copyChangeList(Long[] versions, ConfigBean bean) throws Exception {
        pathSet.clear();
        SVNClientManager sm = authSvn(bean.getSvnPath(), bean.getUserName(), bean.getPassword());
        String[] root = new String[]{""};
        List<SVNLogEntry> entries;
        for(Long v : versions){
            entries = getSVNLog(v, v, root);
            copyChangeList(entries, bean.getLocalPath(), bean.getOutPath(), new FileModification(bean));
        }
        sm.dispose();
    }

    public static void copyChangeList(List<SVNLogEntry> entries, String localPath, String outPath, IFileModification fileModification) throws Exception {
        File localFile;
        Map<String, SVNLogEntryPath> changeMap;
        String svnRoot = repository.getFullPath("").replace(
                repository.getRepositoryRoot(false).getPath(), "");
        for(SVNLogEntry entry : entries){
            changeMap = entry.getChangedPaths();
            for(String key : changeMap.keySet()){
                if(SVNUtils.pathSet.contains(key)){
                    continue;
                }
                SVNUtils.pathSet.add(key);
                localFile = new File( localPath + key.replace(svnRoot, "") );
                //key  /code/rtwb.oa
                FileUtils.copyFile( localFile, localFile.getPath().replace(localPath, outPath), fileModification );
            }
        }
    }


    //本地改动代码的复制
    public static void copyModified(File wc, IFileModification fileModification) throws Exception {

        SVNClientManager sm = authSvn(FileUtils.SVN_PATH, FileUtils.USERNAME, FileUtils.PASSWORD);
        File file = new File(FileUtils.OUT_PATH);
        if(file.exists()){
            file.delete();
        }
        copyModified(sm.getStatusClient(), wc, fileModification);
        sm.dispose();
    }

    //本地改动代码的复制
    public static void copyModified(SVNStatusClient sc, File wc, IFileModification fileModification) throws Exception {

        if(wc.isDirectory()){
            if(FileUtils.notChkDir.contains(wc.getPath()))
                return;
            if(!SVNWCUtil.isVersionedDirectory(wc)){
                FileUtils.copyDir(wc, wc.getPath().replace(FileUtils.LOCAL_PATH, FileUtils.OUT_PATH), fileModification);
                System.out.println(wc.getPath());
            } else
                for(File sub:wc.listFiles()){
                    if(sub.isDirectory() && sub.getName().equals(".svn")){
                        continue;
                    }
                    copyModified(sc, sub, fileModification);
                }
        } else {
            /*if(notChkPath.contains(wc.getPath()))
                return;*/
//            SVNStatusClient sc = clientManager.getStatusClient();
            SVNStatus ss = sc.doStatus(wc, false);
            if( ss.getNodeStatus().equals(SVNStatusType.STATUS_MODIFIED) ){
                FileUtils.copyFile( wc, wc.getPath().replace(FileUtils.LOCAL_PATH, FileUtils.OUT_PATH), fileModification );
                System.out.println("m: " + wc.getPath());
            } else if ( ss.getNodeStatus().equals(SVNStatusType.STATUS_UNVERSIONED) ) {
                FileUtils.copyFile( wc, wc.getPath().replace(FileUtils.LOCAL_PATH, FileUtils.OUT_PATH), fileModification );
                System.out.println("u: "+wc.getPath());
            }
        }
    }



    //获取版本信息
    public static List<SVNLogEntry> getSVNLog(long startRevision, long endRevision, String[] codePaths)
    {
        List<SVNLogEntry> entries = new ArrayList();
        try
        {
            repository.log(codePaths,
                    entries,
                    startRevision,
                    endRevision,
                    true,
                    true);
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        return entries;
    }
}
